package com.xufx.thread.liaoxuefeng.thread17_CompletableFuture;

import java.util.concurrent.CompletableFuture;

/**
 * Created by xufx on 2022/1/5 22:38
 * 相比于Future，CompletableFuture可以传入回调对象，当异步任务完成或者发生异常时，自动回调对象的回调方法
 * 创建一个CompletableFuture是通过CompletableFuture.supplyAsync()实现的，它需要一个实现了Supplier接口的对象
 * 相比于Future，CompletableFuture的优势
 *     1. 支持异步回调
 *     2. 多个CompletableFuture可以串行执行也可以并行执行, CompletableFuture可以组合完成非常复杂的流程控制任务：
 *         定义两个串行执行的任务
 */
public class Main {
    public static void main(String[] args) throws InterruptedException {
        //创建异步执行任务
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(Main::fetchPrice);
        //如果执行成功
        cf.thenAccept((result) -> {
            System.out.println("price:" + result);
        });
        //如果发生异常
        cf.exceptionally((e) ->{
            e.printStackTrace();
            return null;
        });
        //主线程不能立刻结束，否则CompletableFuture默认使用的线程池会立刻关闭
        Thread.sleep(200);

        /*----------------------------*/
        CompletableFuture<String> cfQuery = CompletableFuture.supplyAsync(() -> {return queryCode("中国石油");});
        CompletableFuture<Double> cfFetch = cfQuery.thenApplyAsync((code) -> {return fetchPrice(code);});
        // cfFetch成功后打印结果:
        cfFetch.thenAccept((result) -> {
            System.out.println("price: " + result);
        });
        // 主线程不要立刻结束，否则CompletableFuture默认使用的线程池会立刻关闭:
        Thread.sleep(2000);
    }

    static String queryCode(String name) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }
        return "601857";
    }

    static Double fetchPrice(String code) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }
        return 5 + Math.random() * 20;
    }

    static Double fetchPrice() {
        try {
            Thread.sleep(100);
        }catch (InterruptedException e){

        }
        if (Math.random() < 0.3){
            throw new RuntimeException("fetch price failed");
        }
        return Double.valueOf(8);
    }
}
